package com.mvc.finance.web;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.extremecomponents.table.limit.Limit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import com.mvc.PdfUtils;
import com.mvc.ProjectUtils;
import com.mvc.base.model.Company;
import com.mvc.base.model.Supplier;
import com.mvc.base.service.SupplierManager;
import com.mvc.business.model.Order;
import com.mvc.business.service.OrderAssociatedManager;
import com.mvc.business.service.PurchaseManager;
import com.mvc.config.ApplicationConfig;
import com.mvc.finance.model.BankStatement;
import com.mvc.finance.model.BankStatementCharge;
import com.mvc.finance.service.BankStatementManager;
import com.mvc.framework.dao.PropertyFilter;
import com.mvc.framework.model.BaseEntity;
import com.mvc.framework.service.DictionaryFacade;
import com.mvc.framework.service.PageManager;
import com.mvc.framework.util.FileUpDownUtils;
import com.mvc.framework.util.FrameworkContextUtils;
import com.mvc.framework.util.PageSearch;
import com.mvc.framework.util.PageUtils;
import com.mvc.framework.web.PageController;
import com.mvc.portal.service.NotificationManager;
import com.mvc.security.service.UserManager;

@Controller
@RequestMapping("bankStatement")
public class BankStatementController extends PageController<BankStatement> {

	private static final Logger	                     LOGGER	= Logger.getLogger(BankStatementController.class);
	@Autowired
	private BankStatementManager	                 bankStatementManager;

	@Autowired
	private NotificationManager	                     notificationManager;

	@Autowired
	private DictionaryFacade	                     dictionaryFacade;

	@Autowired
	private PurchaseManager	                         purchaseManager;

	@Autowired
	private UserManager<com.mvc.security.model.User>	userManager;

	@Autowired
	private OrderAssociatedManager	                 orderAssociatedManager;

	@Autowired
	private SupplierManager	                         supplierManager;

	protected String handleSave(HttpServletRequest request, ModelMap modelMap, BankStatement order) throws Exception {
		if (order.getGenerateDate() == null) {
			order.setGenerateDate(new Date());
			order.setFinanceStatus(Order.ORDER_FINANCE_STATUS_UNPAY);
			order.setMakerUserId(FrameworkContextUtils.getCurrentUserId());
			order.setStatus(BankStatement.STATUS_SUBMIT);
		}
		getEntityManager().save(order);
		return "redirect:edit/" + ((BaseEntity) order).getId() + getMessage("common.base.success", request) + "&action="
		        + request.getParameter("action");
	}

	protected String handlePage(HttpServletRequest request, PageSearch page) {
		request.setAttribute("action", "page");
		request.setAttribute("suppliers", supplierManager.getAll());
		return super.handlePage(request, page);
	}

	protected String handleEdit(HttpServletRequest request, HttpServletResponse response, Integer id) throws Exception {
		if (null == id) {
			BankStatement entity = new BankStatement();
			// Invalid object id
			entity.setObjectId(-bankStatementManager.createSystemId());
			request.setAttribute("entity", entity);
		} else {
			BankStatement entity = getEntityManager().get(id);
			request.setAttribute("entity", entity);
			request.setAttribute("purchaseNo", orderAssociatedManager.getBankStatementPurchaseStr(entity.getObjectId()));
		}
		request.setAttribute("units", dictionaryFacade.getDictionariesByDictionaryId(1008));
		return super.handleEdit(request, response, id);
	}

	@RequestMapping("supplier")
	public String supplier(HttpServletRequest request) {
		Limit limit = PageUtils.getLimit(request);
		PageSearch page = preparePage(request, limit);
		page.getFilters().add(new PropertyFilter("EQI_supplierId", String.valueOf(request.getSession().getAttribute("supplierId"))));
		String result = handlePage(request, page);
		afterPage(request, page, IS_NOT_BACK);
		request.setAttribute("action", "supplier");
		return result;
	}

	@RequestMapping("print/{orderId}")
	public String print(HttpServletRequest request, @PathVariable Integer orderId) {
		Map<String, Object> model = prepareOrderData(orderId, request);
		String orderContent = notificationManager.getTemplateString("bankStatement.html", model);
		request.setAttribute("orderContent", orderContent);
		return getFileBasePath() + "printBankStatement";
	}

	@RequestMapping("notify/{orderId}")
	public String notify(@PathVariable Integer orderId, String purchasers, Boolean customer, ModelMap modelMap, HttpServletRequest request) {
		boolean result = false;
		try {
			String userEmails = purchasers;
			userEmails += ProjectUtils.EMAIL_SPLIT + request.getParameter("others");
			if (StringUtils.isNotBlank(userEmails) || customer) {
				Map<String, Object> model = prepareOrderData(orderId, request);
				String orderContent = notificationManager.getTemplateString("bankStatement.html", model);
				BankStatement order = (BankStatement) model.get("entity");
				if (customer) {
					Supplier supplier = supplierManager.getByObjectId(order.getSupplierId());
					userEmails += ProjectUtils.EMAIL_SPLIT + supplier.getEmail();
				}
				String[] to = ProjectUtils.getMailTo(userEmails);
				if (to != null && to.length > 0) {
					Company company = order.getCompany();
					String header = ProjectUtils.getPdfHeader(company);
					String footer = ProjectUtils.getPdfFooter(company);
					File file = PdfUtils.htmlToPdf(orderContent, header, footer);
					String subject = "对帐单(" + company.getName() + ":" + order.getNo() + ")";
					notificationManager.sendMail(subject, ProjectUtils.getCNNoReplyMessage(), new File[] { file },
					        new String[] { order.getNo() + ".pdf" }, to, new String[] {}, true);
					result = true;
				}
			}
		} catch (Exception e) {
			LOGGER.error("notify", e);
		}
		modelMap.addAttribute("result", result);
		return "jsonView";
	}

	@RequestMapping("download/{orderId}")
	public String download(@PathVariable Integer orderId, HttpServletRequest request, HttpServletResponse response) {
		try {
			Map<String, Object> model = prepareOrderData(orderId, request);
			String orderContent = notificationManager.getTemplateString("bankStatement.html", model);
			BankStatement order = (BankStatement) model.get("entity");
			Company company = order.getCompany();
			String header = ProjectUtils.getPdfHeader(company);
			String footer = ProjectUtils.getPdfFooter(company);
			File file = PdfUtils.htmlToPdf(orderContent, header, footer);
			FileUpDownUtils.setDownloadResponseHeaders(response, order.getNo() + ".pdf");
			FileUpDownUtils.downloadFile(file, response);
		} catch (Exception e) {
			LOGGER.error("download", e);
		}
		return null;
	}

	protected Map<String, Object> prepareOrderData(Integer orderId, HttpServletRequest request) {
		BankStatement order = bankStatementManager.getObject(orderId);
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("entity", order);
		model.put("orderItems", order.getBankStatementItems());
		List<BankStatementCharge> charges1 = new ArrayList<BankStatementCharge>();
		List<BankStatementCharge> charges2 = new ArrayList<BankStatementCharge>();
		for (BankStatementCharge charge : order.getBankStatementCharges()) {
			if (charge.getType() == BankStatementCharge.TYPE_FEE) {
				charges1.add(charge);
			} else if (charge.getType() == BankStatementCharge.TYPE_DEBIT) {
				charges2.add(charge);
			}
		}
		String purchaseNos = orderAssociatedManager.getBankStatementPurchaseStr(orderId);
		model.put("maker", userManager.getByObjectId(order.getMakerUserId()));
		model.put("comfirmer", userManager.getByObjectId(order.getConfirmuUserId()));
		model.put("chargeItems1", charges1);
		model.put("chargeItems2", charges2);
		model.put("purchaseNos", purchaseNos);
		model.put("staticDomain", ProjectUtils.getFullCssThemePath());
		model.put("groupName", ApplicationConfig.getGroupName());
		request.setAttribute("entity", order);
		request.setAttribute("staticDomain", ProjectUtils.getFullCssThemePath());
		model.put("currency", dictionaryFacade.getDictionaryByDictionaryIdAndValue(1006, order.getCurrency()).getName());
		model.put("groupName", ApplicationConfig.getGroupName());
		request.setAttribute("entity", order);
		request.setAttribute("currency", dictionaryFacade.getDictionaryByDictionaryIdAndValue(1006, order.getCurrency()).getName());
		return model;
	}

	@RequestMapping("confirm/{orderId}")
	public String confirm(HttpServletRequest request, ModelMap modelMap, @PathVariable Integer orderId) {
		boolean result = false;
		if (orderId != null) {
			try {
				BankStatement order = bankStatementManager.getByObjectId(orderId);
				if (order != null && order.getStatus() != BankStatement.STATUS_COMFIRMED) {
					order.setStatus(BankStatement.STATUS_COMFIRMED);
					order.setConfirmuUserId(FrameworkContextUtils.getCurrentUserId());
					order.setConfirmDate(new Date());
					bankStatementManager.save(order);
					result = true;
				}

			} catch (Exception e) {
				LOGGER.error("confirm" + orderId, e);
			}
		}
		modelMap.put("result", result);
		return "jsonView";
	}

	@RequestMapping("audit/{orderId}")
	public String audit(HttpServletRequest request, ModelMap modelMap, @PathVariable Integer orderId) {
		boolean result = false;
		if (orderId != null) {
			try {
				BankStatement order = bankStatementManager.getByObjectId(orderId);
				if (order != null && order.getStatus() != BankStatement.STATUS_APPROVAED) {
					order.setStatus(BankStatement.STATUS_APPROVAED);
					order.setApprovalUserId(FrameworkContextUtils.getCurrentUserId());
					order.setApprovalDate(new Date());
					bankStatementManager.save(order);
					result = true;
				}

			} catch (Exception e) {
				LOGGER.error("audit" + orderId, e);
			}
		}
		modelMap.put("result", result);
		return "jsonView";
	}

	@RequestMapping("pay/{orderId}")
	public String pay(HttpServletRequest request, @PathVariable Integer orderId, ModelMap modelMap) throws Exception {
		boolean result = false;
		if (orderId != null) {
			try {
				BankStatement order = bankStatementManager.getByObjectId(orderId);
				if (order != null && order.getFinanceStatus() == Order.ORDER_FINANCE_STATUS_UNPAY) {
					order.setFinanceStatus(Order.ORDER_FINANCE_STATUS_PAYED);
					order.setPayDate(new Date());
					bankStatementManager.save(order);
				}
				result = true;
			} catch (Exception e) {
				LOGGER.error("pay:" + orderId, e);
			}
		}
		modelMap.put("result", result);
		return "jsonView";
	}

	@Override
	public PageManager<BankStatement> getEntityManager() {
		return bankStatementManager;
	}

	@Override
	public String getFileBasePath() {
		return "finance/";
	}

}
